package com.jyy.prefabricated.service;

import com.jyy.prefabricated.dto.SysUserDto;
import com.jyy.prefabricated.dto.TrainingOrganizationDto;
import com.jyy.prefabricated.dto.UserRoleDto;
import com.jyy.prefabricated.entity.*;
import com.jyy.prefabricated.enums.BaseStatusEnum;
import com.jyy.prefabricated.enums.OrderTypeEnum;
import com.jyy.prefabricated.enums.PayStatusEnum;
import com.jyy.prefabricated.enums.UserTypeEnum;
import com.jyy.prefabricated.exception.CustomException;
import com.jyy.prefabricated.mapper.*;
import com.jyy.prefabricated.utils.DateUtils;
import com.jyy.prefabricated.vo.StudentExamScoreVo;
import com.jyy.prefabricated.vo.TrainingOrganizationBuyExamVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @version 1.0.0
 * @author: zjj
 */
@Service
@Transactional
public class TrainingOrganizationService {

    @Autowired
    private TrainingOrganizationMapper trainingOrganizationMapper;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private TrainingOrganizationCanBuyProjectMapper canBuyProjectMapper;

    @Autowired
    private TrainingOrganizationCanBuyCourseMapper canBuyCourseMapper;

    @Autowired
    private TrainingOrganizationCanBuyCoursePackageMapper canBuyCoursePackageMapper;

    @Autowired
    private CompanyAdService companyAdService;

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Resource
    private ExamMapper examMapper;

    @Resource
    private StudentExamMapper studentExamMapper;

    @Autowired
    private SmsRecordService smsRecordService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 新增
     *
     * @param dto
     * @return
     */
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public int insert(TrainingOrganizationDto dto) {
        TrainingOrganization trainingOrganization = new TrainingOrganization();
        BeanUtils.copyProperties(dto, trainingOrganization);
        trainingOrganization.setStatus(BaseStatusEnum.VALID.getValue());
        trainingOrganization.setAccount(dto.getTel());
        //生成相关系统账号,这里先生成系统账号判断账号是否已存在
        SysUserDto user = generateUser(trainingOrganization);

        int userId = sysUserService.createUser(user);
        putRole(userId, dto.getRecruit());
        trainingOrganizationMapper.insert(trainingOrganization);
        //保存培训机构可购项目
        saveTrainingOrganizationCanBuyProject(dto, trainingOrganization.getId());
        //保存培训机构可购课程
        saveTrainingOrganizationCanBuyCourse(dto, trainingOrganization.getId());
        //保存培训机构可购课程包
        saveTrainingOrganizationCanBuyCoursePackage(dto, trainingOrganization.getId());
        return trainingOrganization.getId();
    }

    /**
     * 新增
     *
     * @param dto
     * @return
     */
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public int insertLogin(TrainingOrganizationDto dto) {
        TrainingOrganization trainingOrganization = new TrainingOrganization();
        BeanUtils.copyProperties(dto, trainingOrganization);
        trainingOrganization.setStatus(BaseStatusEnum.VALID.getValue());
        trainingOrganization.setAccount(dto.getTel());
        //生成相关系统账号,这里先生成系统账号判断账号是否已存在
        SysUserDto user = generateUserLogin(trainingOrganization);
        int userId = sysUserService.createUserLogin(user);

        putRole(userId, dto.getRecruit());
        TrainingOrganization to = trainingOrganizationMapper.selectByAccount(dto.getTel());
        if (to == null) {
            trainingOrganizationMapper.insert(trainingOrganization);
        }

        //保存培训机构可购项目
        saveTrainingOrganizationCanBuyProject(dto, trainingOrganization.getId());
        //保存培训机构可购课程
        saveTrainingOrganizationCanBuyCourse(dto, trainingOrganization.getId());
        //保存培训机构可购课程包
        saveTrainingOrganizationCanBuyCoursePackage(dto, trainingOrganization.getId());
        return userId;
    }

    /**
     * 通过注册申请
     *
     * @param register
     */
    public void applyRegister(TrainingOrganizationRegister register) {
        TrainingOrganization trainingOrganization = new TrainingOrganization();
        BeanUtils.copyProperties(register, trainingOrganization);
        trainingOrganization.setId(null);
        trainingOrganization.setStatus(BaseStatusEnum.VALID.getValue());
        trainingOrganization.setRecruit(false);
        trainingOrganization.setAccount(register.getTel());
        SysUserDto user = generateUser(trainingOrganization);
        user.setPassword(register.getPassword());
        int userId = sysUserService.createUser(user);
        putRole(userId, trainingOrganization.getRecruit());
        trainingOrganizationMapper.insert(trainingOrganization);
    }

    /**
     * 通过机构信息生成相关账号
     *
     * @param dto
     * @return
     */
    private SysUserDto generateUser(TrainingOrganization dto) {
        SysUser checkUser = sysUserService.selectByUsername(dto.getTel());
        if (checkUser != null) {
            throw new CustomException("当前手机号已存在");
        }
        SysUserDto user = new SysUserDto();
        user.setUsername(dto.getTel());
        user.setChannelCode(dto.getChannelCode());
        user.setName(dto.getName());
        user.setMobile(dto.getTel());
        user.setEmail(dto.getEmail());
        user.setUserType(UserTypeEnum.TRAININGORGANIZATION.getValue());
        user.setPassword(dto.getTel());
        user.setStatus(BaseStatusEnum.VALID.getValue());
        user.setInviter(dto.getChannelCode());
        return user;
    }

    /**
     * 通过机构信息生成相关账号()
     *
     * @param dto
     * @return
     */
    private SysUserDto generateUserLogin(TrainingOrganization dto) {
        SysUserDto user = new SysUserDto();
        user.setUsername(dto.getTel());
        user.setChannelCode(dto.getChannelCode());
        user.setName(dto.getName());
        user.setMobile(dto.getTel());
        user.setEmail(dto.getEmail());
        user.setUserType(UserTypeEnum.TRAININGORGANIZATION.getValue());
        user.setPassword(dto.getTel());
        user.setStatus(BaseStatusEnum.VALID.getValue());
        user.setInviter(dto.getChannelCode());
        return user;
    }

    /**
     * 给机构权限赋值
     */
    public void putRole(Integer userId, Boolean recruit) {
        UserRoleDto dto = new UserRoleDto();
        dto.setUserId(userId);
        List<Integer> roleIds = new ArrayList<>();
        //赋予机构权限
        roleIds.add(6);
        //判断是否赋予招聘权限
        if (recruit != null && recruit) {
            roleIds.add(10);
        }
        dto.setRoleIds(roleIds);
        sysUserService.putUserRoles(dto);
    }

    /**
     * 保存机构可购项目
     *
     * @param dto
     * @param trainingOrganizationId
     */
    public void saveTrainingOrganizationCanBuyProject(TrainingOrganizationDto dto, Integer trainingOrganizationId) {
        if (dto.getProjectIds().size() > 0) {
            List<TrainingOrganizationCanBuyProject> projects = new ArrayList<>();
            for (Integer projectId : dto.getProjectIds()) {
                TrainingOrganizationCanBuyProject project = new TrainingOrganizationCanBuyProject();
                project.setProjectId(projectId);
                project.setTrainingOrganizationId(trainingOrganizationId);
                projects.add(project);
            }
            if (projects != null && projects.size() > 0) {
                canBuyProjectMapper.batchInsert(projects);
            }
        }
    }

    /**
     * 保存机构可购课程
     *
     * @param dto
     * @param trainingOrganizationId
     */
    public void saveTrainingOrganizationCanBuyCourse(TrainingOrganizationDto dto, Integer trainingOrganizationId) {
        if (dto.getCourseIds().size() > 0) {
            List<TrainingOrganizationCanBuyCourse> canBuyCourses = new ArrayList<>();
            for (Integer courseId : dto.getCourseIds()) {
                TrainingOrganizationCanBuyCourse canBuyCourse = new TrainingOrganizationCanBuyCourse();
                canBuyCourse.setCourseId(courseId);
                canBuyCourse.setTrainingOrganizationId(trainingOrganizationId);
                canBuyCourses.add(canBuyCourse);
            }
            if (canBuyCourses != null && canBuyCourses.size() > 0) {
                canBuyCourseMapper.batchInsert(canBuyCourses);
            }
        }
    }

    /**
     * 保存机构可购课程包
     *
     * @param dto
     * @param trainingOrganizationId
     */
    public void saveTrainingOrganizationCanBuyCoursePackage(TrainingOrganizationDto dto, Integer trainingOrganizationId) {
        if (dto.getCoursePackageIds().size() > 0) {
            List<TrainingOrganizationCanBuyCoursePackage> canBuyCoursePackages = new ArrayList<>();
            for (Integer packageId : dto.getCoursePackageIds()) {
                TrainingOrganizationCanBuyCoursePackage canBuyCoursePackage = new TrainingOrganizationCanBuyCoursePackage();
                canBuyCoursePackage.setPackageId(packageId);
                canBuyCoursePackage.setTrainingOrganizationId(trainingOrganizationId);
                canBuyCoursePackages.add(canBuyCoursePackage);
            }
            if (canBuyCoursePackages != null && canBuyCoursePackages.size() > 0) {
                canBuyCoursePackageMapper.batchInsert(canBuyCoursePackages);
            }
        }
    }

    /**
     * 更新
     *
     * @param dto
     * @return
     */
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public int update(TrainingOrganizationDto dto) {
        if (dto.getId() == null) {
            throw new CustomException("参数id不能为空");
        }
        TrainingOrganization trainingOrganization = trainingOrganizationMapper.selectByPrimaryKey(dto.getId());
        if (dto.getContent() != null && dto.getImage() != null) {
            if (!dto.getContent().equals(trainingOrganization.getContent()) || !dto.getImage().equals(trainingOrganization.getImage())) {
                //企业简介和图片改变时更新广告状态
                List<CompanyAd> companyAds = companyAdService.selectByTo(dto.getId(), null, null);
                if (companyAds.size() > 0) {
                    Calendar cal = Calendar.getInstance();
                    for (CompanyAd ad : companyAds) {
                        ad.setImage(dto.getImage());
                        ad.setContent(dto.getContent());
                        if (ad.getContent() == null && ad.getImage() == null) {
                            Date startTime = new Date();
                            cal.setTime(startTime);
                            long days = DateUtils.pastDays(ad.getStartTime(), ad.getEndTime());
                            cal.add(Calendar.DATE, (int) days);
                            ad.setStartTime(startTime);
                            ad.setEndTime(cal.getTime());
                            ad.setStatus(BaseStatusEnum.VALID.getValue());
                        }

                    }
                    companyAdService.batchUpdate(companyAds);
                }
            }
        }
        //同步修改机构相关用户
        SysUser sysUser = sysUserService.selectByUsername(trainingOrganization.getTel());
        SysUser checkUser = sysUserService.selectByUsername(dto.getTel());
        if (checkUser != null && !checkUser.getId().equals(sysUser.getId())) {
            throw new CustomException("当前手机号已存在");
        }
        if (dto.getTel() != null && !sysUser.getUsername().equals(dto.getTel())) {
            smsRecordService.checkCode(dto.getTel(), dto.getValidateCode());
            if (!passwordEncoder.matches(dto.getPassword(), sysUser.getPassword())) {
                throw new CustomException("密码不正确！");
            }
        }
        sysUser.setUsername(dto.getTel());
        sysUser.setName(dto.getName());
        sysUser.setMobile(dto.getTel());
        sysUserService.update(sysUser);
        BeanUtils.copyProperties(dto, trainingOrganization);
        trainingOrganization.setAccount(trainingOrganization.getTel());
        int row = trainingOrganizationMapper.updateByPrimaryKeySelective(trainingOrganization);
        //修改权限
        putRole(sysUser.getId(), trainingOrganization.getRecruit());
        //保存培育机构可购项目
        canBuyProjectMapper.deleteByTrainingOrganizationId(dto.getId());
        canBuyCourseMapper.deleteByTrainingOrganizationId(dto.getId());
        canBuyCoursePackageMapper.deleteByTrainingOrganizationId(dto.getId());
        saveTrainingOrganizationCanBuyProject(dto, trainingOrganization.getId());
        saveTrainingOrganizationCanBuyCourse(dto, trainingOrganization.getId());
        saveTrainingOrganizationCanBuyCoursePackage(dto, trainingOrganization.getId());
        return row;
    }

    public int judgeTel(Integer id, String tel) {
        TrainingOrganization trainingOrganization = trainingOrganizationMapper.selectByPrimaryKey(id);
        //同步修改机构相关用户
        SysUser sysUser = sysUserService.selectByUsername(trainingOrganization.getTel());
        SysUser checkUser = sysUserService.selectByUsername(tel);
        if (checkUser != null && !checkUser.getId().equals(sysUser.getId())) {
            throw new CustomException("当前手机号已存在");
        }
        return 0;
    }

    /**
     * 更新状态
     *
     * @param id
     * @return
     */
    public int updateStatus(Integer id) {
        TrainingOrganization organization = trainingOrganizationMapper.selectByPrimaryKey(id);
        if (organization == null) {
            throw new CustomException("当前机构不存在");
        }
        SysUser user = sysUserService.selectByUsername(organization.getAccount());
        if (organization.getStatus().equals(BaseStatusEnum.VALID.getValue())) {
            organization.setStatus(BaseStatusEnum.INVALID.getValue());
        } else {
            organization.setStatus(BaseStatusEnum.VALID.getValue());
        }
        sysUserService.updateStatus(user.getId());
        return trainingOrganizationMapper.updateByPrimaryKeySelective(organization);
    }

    /**
     * 重置培训机构密码
     *
     * @param account
     * @param pwd
     * @return
     */
    public int resetTrainingOrganizationPwd(String account, String pwd) {
        return sysUserService.resetPwdByAccount(account, pwd);
    }

    /**
     * 通过机构账号查询机构
     *
     * @param account
     * @return
     */
    public TrainingOrganization selectByAccount(String account) {
        return trainingOrganizationMapper.selectByAccount(account);
    }

    /**
     * 删除机构
     *
     * @param id
     * @return
     */
    public int delete(Integer id) {
        TrainingOrganization organization = trainingOrganizationMapper.selectByPrimaryKey(id);
        if (organization == null) {
            throw new CustomException("当前机构不存在");
        }
        SysUser user = sysUserService.selectByUsername(organization.getAccount());
        user.setStatus(BaseStatusEnum.INVALID.getValue());
        sysUserMapper.updateByPrimaryKeySelective(user);
        return trainingOrganizationMapper.deleteByPrimaryKey(id);

    }

    /**
     * 根据id查询
     *
     * @param id
     * @return
     */
    public TrainingOrganization selectById(Integer id) {
        return trainingOrganizationMapper.selectByPrimaryKey(id);
    }

    /**
     * 根据参数查询
     *
     * @param name            名称
     * @param province        省
     * @param city            市
     * @param status          状态
     * @param courseId        课程id
     * @param coursePackageId 课程包id
     * @param projectId       项目id
     * @return
     */
    public List<TrainingOrganization> selectByParams(String name, String province, String city, Integer status, Integer courseId, Integer coursePackageId, Integer projectId) {
        return trainingOrganizationMapper.selectByParams(name, province, city, status, courseId, coursePackageId, projectId);
    }

    /**
     * 查询所有机构地区信息
     *
     * @return
     */
    public List<Map<String, Object>> findAreaList() {
        List<TrainingOrganization> trainingOrganizations = trainingOrganizationMapper.selectByParams(null, null, null, BaseStatusEnum.VALID.getValue(), null, null, null);
        List<Map<String, Object>> areas = new ArrayList<>();
        List<String> provinces = trainingOrganizations.stream().filter(e -> StringUtils.isNotBlank(e.getProvince())).map(TrainingOrganization::getProvince).distinct().collect(Collectors.toList());
        for (String province : provinces) {
            Map<String, Object> map = new HashMap<>();
            map.put("label", province);
            List<Map<String, Object>> children = new ArrayList<>();
            List<String> cities = trainingOrganizations.stream().filter(e -> e.getProvince().equals(province) && StringUtils.isNotBlank(e.getCity())).map(TrainingOrganization::getCity).distinct().collect(Collectors.toList());
            for (String city : cities) {
                Map<String, Object> child = new HashMap<>();
                child.put("label", city);
                children.add(child);
            }
            map.put("children", children);
            areas.add(map);
        }
        return areas;
    }

    public List<TrainingOrganizationBuyExamVo> selectBuyExam(Integer trainingOrganizationId, Integer userId) {
        List<TrainingOrganizationBuyExamVo> result = new ArrayList<>();

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setBuyerId(userId);
        orderInfo.setPayStatus(PayStatusEnum.SUCCESS.getCode());
        orderInfo.setOrderType(OrderTypeEnum.Exam.getValue());
        List<OrderInfo> orders = orderInfoMapper.selectOrders(orderInfo);
        if (orders != null && orders.size() > 0) {
            List<Integer> examIdList = orders.stream().map(e -> e.getProductId()).collect(Collectors.toList());
            if (examIdList != null && examIdList.size() > 0) {

                for (Integer id : examIdList) {
                    Exam exam = examMapper.selectByPrimaryKey(id);
                    TrainingOrganizationBuyExamVo trainingOrganizationBuyExamVo = new TrainingOrganizationBuyExamVo();
                    BeanUtils.copyProperties(exam, trainingOrganizationBuyExamVo);

                    //统计该企业下学员参加该考试的人数
                    List<StudentExamScoreVo> studentExamVoList = selectExamRecord(id, trainingOrganizationId);
                    if (studentExamVoList != null && studentExamVoList.size() > 0) {
                        trainingOrganizationBuyExamVo.setNumber(studentExamVoList.size());
                    } else {
                        trainingOrganizationBuyExamVo.setNumber(0);
                    }
                    result.add(trainingOrganizationBuyExamVo);
                }
            }
        }
        return result;
    }

    public List<StudentExamScoreVo> selectExamRecord(Integer examId, Integer trainingOrganizationId) {
        List<StudentExamScoreVo> result = studentExamMapper.selectExamScoreByParams(null, null, null, null, trainingOrganizationId, null, null, examId, null);
        if (result != null && result.size() > 0) {
            for (StudentExamScoreVo studentExamScoreVo : result) {
                Exam exam = examMapper.selectByPrimaryKey(studentExamScoreVo.getExamId());
                if (exam.getPassGrade() == null) {
                    exam.setPassGrade(0d);
                }
                if (studentExamScoreVo.getTotalScore() >= exam.getPassGrade()) {
                    studentExamScoreVo.setIsPass(true);
                }
            }
        }
        return result;
    }
}
